import clang.cindex
import os
import sys
from clang.cindex import TranslationUnit
#clang.set_library_path("/usr/lib/clang/6.0/lib/linux/")
index = clang.cindex.Index.create()
if not sys.argv[1].endswith('.c'):
  sys.exit(1)
text = open(sys.argv[1]).read()
tu = index.parse(sys.argv[1], ['-DINLINE="static inline"', "-I.", "-I/usr/lib/clang/10.0.0/include/"], options=TranslationUnit.PARSE_INCOMPLETE)
ls = []
s = []
def recur(node, indent = 0):
  if node.kind == clang.cindex.CursorKind.FUNCTION_DECL and node.is_definition() and node.storage_class != clang.cindex.StorageClass.STATIC:
    #print(len(ls), node.result_type.spelling, node.displayname)
    s.append(node)
    ls.append(node.result_type.spelling + ' ' + node.displayname)
  for child in node.get_children():
    recur(child, indent + 1)

recur(tu.cursor)
def extract_decl(node):
  decl_start = node.extent.start
  for child in node.get_children():
    if child.kind ==  clang.cindex.CursorKind.COMPOUND_STMT:
      decl_end = child.extent.start
  if decl_start.file.name == decl_end.file.name:
    if decl_start.file.name == sys.argv[1]:
      return text[decl_start.offset : decl_end.offset].strip()
    else:
      return open(decl_start.file.name).read()[decl_start.offset : decl_end.offset].strip()
  else:
    return node.result_type.spelling + ' ' + node.displayname

prefix = os.path.splitext(sys.argv[1])[0]
hdr = prefix + '.h'
print(hdr)
guard = prefix.upper() + '_H_'
sig_st = "//function signatures"
sig_ed = "//end function signatures"
if not os.path.exists(hdr):
  f = open(hdr, "w")
  f.write('#ifndef %s\n' % guard)
  f.write('#define %s\n' % guard)
  f.write(sig_st + '\n')
  for sig in ls:
    f.write("%s;\n" % sig)
  f.write(sig_ed + '\n')
  f.write('#endif\n')
else:
  old_lines = open(hdr).readlines()
  has_guard = False
  if old_lines[0].startswith('#ifndef') and old_lines[1].startswith('#define'):
    while old_lines:
      line = old_lines[-1]
      if not line.strip():
        old_lines.pop()
        continue
      else:
        if old_lines[-1].startswith('#endif'):
          has_guard = True
          old_lines.pop()
        break
  if has_guard:
    old_lines = old_lines[2:]
  in_sig = False
  f = open(hdr, "w")
  f.write('#ifndef %s\n' % guard)
  f.write('#define %s\n' % guard)
  for line in old_lines:
    if line.startswith(sig_st):
      in_sig = True
    elif line.startswith(sig_ed):
      in_sig = False
    elif not in_sig:
      f.write(line)
  f.write(sig_st + '\n')
  for node in s:
    f.write("%s;\n" % extract_decl(node))
  f.write(sig_ed + '\n')
  f.write('#endif\n')
  f.close()
#fd = next(filter(lambda x: , tu.cursor.get_children()))